home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / misc / memtest8.000 / memtest8 / memtest86 / bootsect.S next >
Encoding:
Text File  |  1996-01-01  |  7.7 KB  |  409 lines

  1. !
  2. !    bootsect.s        Copyright (C) 1991, 1992 Linus Torvalds
  3. !
  4. ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
  5. ! itself out of the way to address 0x90000, and jumps there.
  6. !
  7. ! It then loads 'setup' directly after itself (0x90200), and the system
  8. ! at 0x10000, using BIOS interrupts. 
  9. !
  10. ! The loader has been made as simple as possible, and continuos
  11. ! read errors will result in a unbreakable loop. Reboot by hand. It
  12. ! loads pretty fast by getting whole tracks at a time whenever possible.
  13.  
  14. ! 1-Jan-96 Modified by Chris Brady for use as a boot loader for MemTest-86.
  15.  
  16. #include "mtest.h"
  17.  
  18. .text
  19.  
  20. ROOT_DEV = 0
  21.  
  22. ! ld86 requires an entry symbol. This may as well be the usual one.
  23. .globl    _main
  24. _main:
  25.     mov    ax,#BOOTSEG
  26.     mov    ds,ax
  27.     mov    ax,#INITSEG
  28.     mov    es,ax
  29.     mov    cx,#256
  30.     sub    si,si
  31.     sub    di,di
  32.     cld
  33.     rep
  34.     movsw
  35.     jmpi    go,INITSEG
  36.  
  37. go:    mov    ax,cs        
  38.     mov    dx,#0x4000-12    ! 0x4000 is arbitrary value >= length of
  39.                 ! bootsect + length of setup + room for stack
  40.                 ! 12 is disk parm size
  41.  
  42. ! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
  43. ! wouldn't have to worry about this if we checked the top of memory.  Also
  44. ! my BIOS can be configured to put the wini drive tables in high memory
  45. ! instead of in the vector table.  The old stack might have clobbered the
  46. ! drive table.
  47.  
  48.     mov    ds,ax
  49.     mov    es,ax
  50.     mov    ss,ax        ! put stack at INITSEG:0x4000-12.
  51.     mov    sp,dx
  52. /*
  53.  *    Many BIOS's default disk parameter tables will not 
  54.  *    recognize multi-sector reads beyond the maximum sector number
  55.  *    specified in the default diskette parameter tables - this may
  56.  *    mean 7 sectors in some cases.
  57.  *
  58.  *    Since single sector reads are slow and out of the question,
  59.  *    we must take care of this by creating new parameter tables
  60.  *    (for the first disk) in RAM.  We will set the maximum sector
  61.  *    count to 18 - the most we will encounter on an HD 1.44.  
  62.  *
  63.  *    High doesn't hurt.  Low does.
  64.  *
  65.  *    Segments are as follows: ds=es=ss=cs - INITSEG,
  66.  *        fs = 0, gs = parameter table segment
  67.  */
  68.  
  69.     push    #0
  70.     pop    fs
  71.     mov    bx,#0x78        ! fs:bx is parameter table address
  72.     seg fs
  73.     lgs    si,(bx)            ! gs:si is source
  74.  
  75.     mov    di,dx            ! es:di is destination
  76.     mov    cx,#6            ! copy 12 bytes
  77.     cld
  78.  
  79.     rep
  80.     seg gs
  81.     movsw
  82.  
  83.     mov    di,dx
  84.     movb    4(di),*18        ! patch sector count
  85.  
  86.     seg fs
  87.     mov    (bx),di
  88.     seg fs
  89.     mov    2(bx),es
  90.  
  91.     mov    ax,cs
  92.     mov    fs,ax
  93.     mov    gs,ax
  94.     
  95.     xor    ah,ah            ! reset FDC 
  96.     xor    dl,dl
  97.     int     0x13    
  98.  
  99. ! load the setup-sectors directly after the bootblock.
  100. ! Note that 'es' is already set up.
  101.  
  102. load_setup:
  103.     xor    dx, dx            ! drive 0, head 0
  104.     mov    cx,#0x0002        ! sector 2, track 0
  105.     mov    bx,#0x0200        ! address = 512, in INITSEG
  106.     mov    ax,#0x0200+SETUPSECS    ! service 2, nr of sectors
  107.                     ! (assume all on head 0, track 0)
  108.     int    0x13            ! read it
  109.     jnc    ok_load_setup        ! ok - continue
  110.  
  111.     push    ax            ! dump error code
  112.     call    print_nl
  113.     mov    bp, sp
  114.     call    print_hex
  115.     pop    ax    
  116.     
  117.     xor    dl, dl            ! reset FDC
  118.     xor    ah, ah
  119.     int    0x13
  120.     jmp    load_setup
  121.  
  122. ok_load_setup:
  123.  
  124. ! Get disk drive parameters, specifically nr of sectors/track
  125.  
  126. #if 0
  127.  
  128. ! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
  129. ! disks.  It doesn't work for one of my BIOS's (1987 Award).  It was
  130. ! fatal not to check the error code.
  131.  
  132.     xor    dl,dl
  133.     mov    ah,#0x08        ! AH=8 is get drive parameters
  134.     int    0x13
  135.     xor    ch,ch
  136. #else
  137.  
  138. ! It seems that there is no BIOS call to get the number of sectors.  Guess
  139. ! 18 sectors if sector 18 can be read, 15 if sector 15 can be read.
  140. ! Otherwise guess 9.
  141.  
  142.     xor    dx, dx            ! drive 0, head 0
  143.     mov    cx,#0x0012        ! sector 18, track 0
  144.     mov    bx,#0x0200+SETUPSECS*0x200  ! address after setup (es = cs)
  145.     mov    ax,#0x0201        ! service 2, 1 sector
  146.     int    0x13
  147.     jnc    got_sectors
  148.     mov    cl,#0x0f        ! sector 15
  149.     mov    ax,#0x0201        ! service 2, 1 sector
  150.     int    0x13
  151.     jnc    got_sectors
  152.     mov    cl,#0x09
  153.  
  154. #endif
  155.  
  156. got_sectors:
  157.     seg cs
  158.     mov    sectors,cx
  159.     mov    ax,#INITSEG
  160.     mov    es,ax
  161.  
  162. ! Print some inane message
  163.  
  164.     mov    ah,#0x03        ! read cursor pos
  165.     xor    bh,bh
  166.     int    0x10
  167.     
  168.     mov    cx,#9
  169.     mov    bx,#0x0007        ! page 0, attribute 7 (normal)
  170.     mov    bp,#msg1
  171.     mov    ax,#0x1301        ! write string, move cursor
  172.     int    0x10
  173.  
  174. ! ok, we've written the message, now
  175. ! we want to load the system (at 0x10000)
  176.  
  177.     mov    ax,#TSTLOAD
  178.     mov    es,ax        ! segment of 0x010000
  179.     call    read_it
  180.     call    kill_motor
  181.     call    print_nl
  182.  
  183. ! After that we check which root-device to use. If the device is
  184. ! defined (!= 0), nothing is done and the given device is used.
  185. ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
  186. ! on the number of sectors that the BIOS reports currently.
  187.  
  188.     seg cs
  189.     mov    ax,root_dev
  190.     or    ax,ax
  191.     jne    root_defined
  192.     seg cs
  193.     mov    bx,sectors
  194.     mov    ax,#0x0208        ! /dev/ps0 - 1.2Mb
  195.     cmp    bx,#15
  196.     je    root_defined
  197.     mov    ax,#0x021c        ! /dev/PS0 - 1.44Mb
  198.     cmp    bx,#18
  199.     je    root_defined
  200.     mov    ax,#0x0200        ! /dev/fd0 - autodetect
  201. root_defined:
  202.     seg cs
  203.     mov    root_dev,ax
  204.  
  205. ! after that (everyting loaded), we jump to
  206. ! the setup-routine loaded directly after
  207. ! the bootblock:
  208.  
  209.     jmpi    0,SETUPSEG
  210.  
  211. ! This routine loads the system at address 0x10000, making sure
  212. ! no 64kB boundaries are crossed. We try to load it as fast as
  213. ! possible, loading whole tracks whenever we can.
  214. !
  215. ! in:    es - starting address segment (normally 0x1000)
  216. !
  217. sread:    .word 1+SETUPSECS    ! sectors read of current track
  218. head:    .word 0            ! current head
  219. track:    .word 0            ! current track
  220.  
  221. read_it:
  222.     mov ax,es
  223.     test ax,#0x0fff
  224. die:    jne die            ! es must be at 64kB boundary
  225.     xor bx,bx        ! bx is starting address within segment
  226. rp_read:
  227.     mov ax,es
  228.     sub ax,#TSTLOAD
  229.     cmp ax,syssize        ! have we loaded all yet?
  230.     jbe ok1_read
  231.     ret
  232. ok1_read:
  233.     seg cs
  234.     mov ax,sectors
  235.     sub ax,sread
  236.     mov cx,ax
  237.     shl cx,#9
  238.     add cx,bx
  239.     jnc ok2_read
  240.     je ok2_read
  241.     xor ax,ax
  242.     sub ax,bx
  243.     shr ax,#9
  244. ok2_read:
  245.     call read_track
  246.     mov cx,ax
  247.     add ax,sread
  248.     seg cs
  249.     cmp ax,sectors
  250.     jne ok3_read
  251.     mov ax,#1
  252.     sub ax,head
  253.     jne ok4_read
  254.     inc track
  255. ok4_read:
  256.     mov head,ax
  257.     xor ax,ax
  258. ok3_read:
  259.     mov sread,ax
  260.     shl cx,#9
  261.     add bx,cx
  262.     jnc rp_read
  263.     mov ax,es
  264.     add ah,#0x10
  265.     mov es,ax
  266.     xor bx,bx
  267.     jmp rp_read
  268.  
  269. read_track:
  270.     pusha
  271.     pusha    
  272.     mov    ax, #0xe2e     ! loading... message 2e = .
  273.     mov    bx, #7
  274.      int    0x10
  275.     popa        
  276.  
  277.     mov    dx,track
  278.     mov    cx,sread
  279.     inc    cx
  280.     mov    ch,dl
  281.     mov    dx,head
  282.     mov    dh,dl
  283.     and    dx,#0x0100
  284.     mov    ah,#2
  285.     
  286.     push    dx                ! save for error dump
  287.     push    cx
  288.     push    bx
  289.     push    ax
  290.  
  291.     int    0x13
  292.     jc    bad_rt
  293.     add    sp, #8
  294.     popa
  295.     ret
  296.  
  297. bad_rt:    push    ax                ! save error code
  298.     call    print_all            ! ah = error, al = read
  299.     
  300.     
  301.     xor ah,ah
  302.     xor dl,dl
  303.     int 0x13
  304.     
  305.  
  306.     add    sp, #10
  307.     popa    
  308.     jmp read_track
  309.  
  310. /*
  311.  *    print_all is for debugging purposes.  
  312.  *    It will print out all of the registers.  The assumption is that this is
  313.  *    called from a routine, with a stack frame like
  314.  *    dx 
  315.  *    cx
  316.  *    bx
  317.  *    ax
  318.  *    error
  319.  *    ret <- sp
  320.  *
  321. */
  322.  
  323. print_all:
  324.     mov    cx, #5        ! error code + 4 registers
  325.     mov    bp, sp    
  326.  
  327. print_loop:
  328.     push    cx        ! save count left
  329.     call    print_nl    ! nl for readability
  330.  
  331.     cmp    cl, 5
  332.     jae    no_reg        ! see if register name is needed
  333.     
  334.     mov    ax, #0xe05 + 'A - 1
  335.     sub    al, cl
  336.     int    0x10
  337.  
  338.     mov    al, #'X
  339.     int    0x10
  340.  
  341.     mov    al, #':
  342.     int    0x10
  343.  
  344. no_reg:
  345.     add    bp, #2        ! next register
  346.     call    print_hex    ! print it
  347.     pop    cx
  348.     loop    print_loop
  349.     ret
  350.  
  351. print_nl:
  352.     mov    ax, #0xe0d    ! CR
  353.     int    0x10
  354.     mov    al, #0xa    ! LF
  355.     int     0x10
  356.     ret
  357.  
  358. /*
  359.  *    print_hex is for debugging purposes, and prints the word
  360.  *    pointed to by ss:bp in hexadecmial.
  361. */
  362.  
  363. print_hex:
  364.     mov    cx, #4        ! 4 hex digits
  365.     mov    dx, (bp)    ! load word into dx
  366. print_digit:
  367.     rol    dx, #4        ! rotate so that lowest 4 bits are used
  368.     mov    ah, #0xe    
  369.     mov    al, dl        ! mask off so we have only next nibble
  370.     and    al, #0xf
  371.     add    al, #'0        ! convert to 0-based digit
  372.     cmp    al, #'9        ! check for overflow
  373.     jbe    good_digit
  374.     add    al, #'A - '0 - 10
  375.  
  376. good_digit:
  377.     int    0x10
  378.     loop    print_digit
  379.     ret
  380.  
  381.  
  382. /*
  383.  * This procedure turns off the floppy drive motor, so
  384.  * that we enter the kernel in a known state, and
  385.  * don't have to worry about it later.
  386.  */
  387. kill_motor:
  388.     push dx
  389.     mov dx,#0x3f2
  390.     xor al, al
  391.     outb
  392.     pop dx
  393.     ret
  394.  
  395. sectors:
  396.     .word 0
  397.  
  398. msg1:
  399.     .byte 13,10
  400.     .ascii "Loading"
  401.  
  402. .org 506
  403. syssize:
  404.     .word TSTSIZE/0x10
  405. root_dev:
  406.     .word ROOT_DEV
  407. boot_flag:
  408.     .word 0xAA55
  409.